/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package FEMSolver1D;

import FEMShapeFunction1D.FEMShapeFunction1D1;
import HashMatrix2.HashMatrix2;
import Integration.IFunction1D;
import MathLib.HashMatrix.Gauss;
import MathLib.HashMatrix.HashMatrix;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import syntaxanalyser.PostfiksX;

/**
 *
 * @author mark_o
 */
public class MainMatrixGenerator1{

    //HashMatrix2 A;
    HashMatrix A;
    double[] b;
    ArrayList<Double> NodeList;
    ArrayList<FEMShapeFunction1D1> FuncList;

    String pString="1";
    String wString="0";
    String qString="10";
    String fString="100";


    public MainMatrixGenerator1(ArrayList<Double> NodeList) {
        this.NodeList = NodeList;
        A = new HashMatrix(HashMatrix2.ARRAY_TYPE, NodeList.size());
        b = new double[NodeList.size()];
        generateFunctions();

    }

    private void generateFunctions(){
        FuncList = new ArrayList<FEMShapeFunction1D1>();
        double h = NodeList.get(1) - NodeList.get(0);
        for (int i = 0; i < NodeList.size(); i++) {
            FuncList.add(new FEMShapeFunction1D1(NodeList.get(i), h));
        }
    }

    public void GenerateLU() {
        MatrixGenerator1 gen = new MatrixGenerator1(NodeList.get(0),NodeList.get(NodeList.size()-1));
        IFunction1D p = new IFunction1D() {

            public double calculate(double x) {
                try {
                    return PostfiksX.Calculate(pString, x);
                } catch (Exception ex) {
                    Logger.getLogger(MainMatrixGenerator1.class.getName()).log(Level.SEVERE, null, ex);
                }
                return 0;
            }

            public double calculateDerivaty(double x) {
                throw new UnsupportedOperationException("Not supported yet.");
            }
        };
        IFunction1D w = new IFunction1D() {

            public double calculate(double x) {
                try {
                    return PostfiksX.Calculate(wString, x);
                } catch (Exception ex) {
                    Logger.getLogger(MainMatrixGenerator1.class.getName()).log(Level.SEVERE, null, ex);
                }
                return 0;
            }

            public double calculateDerivaty(double x) {
                throw new UnsupportedOperationException("Not supported yet.");
            }
        };
        IFunction1D q = new IFunction1D() {

            public double calculate(double x) {
                try {
                    return PostfiksX.Calculate(qString, x);
                } catch (Exception ex) {
                    Logger.getLogger(MainMatrixGenerator1.class.getName()).log(Level.SEVERE, null, ex);
                }
                return 0;
            }

            public double calculateDerivaty(double x) {
                throw new UnsupportedOperationException("Not supported yet.");
            }
        };
        IFunction1D f = new IFunction1D() {

            public double calculate(double x) {
                try {
                    return PostfiksX.Calculate(fString, x);
                } catch (Exception ex) {
                    Logger.getLogger(MainMatrixGenerator1.class.getName()).log(Level.SEVERE, null, ex);
                }
                return 0;
            }

            public double calculateDerivaty(double x) {
                throw new UnsupportedOperationException("Not supported yet.");
            }
        };

        for (int i = 0; i < b.length; i++) {
            //IFunction1D f1 = FuncList.get(i);
            gen.setF1(FuncList.get(i));
            gen.setF2(FuncList.get(i));
            A.setValue(i, i, gen.getKe(p)+gen.getAdv(w)+gen.getMe(q));
            for (int j = 0; j < b.length; j++) {
                gen.setF2(FuncList.get(j));
                double val = gen.getKe(p)+gen.getAdv(w)+gen.getMe(q);
                A.setValue(i, j, val);
            }
            b[i] = gen.getFe(f);
        }

        //for (int i = 0; i < b.length; i++) {
        //    for (int j = 0; j < b.length; j++) {
        //        System.out.print(A.getValue(i, j)+"\t");
        //    }
        //    System.out.println("\t"+b[i]);
        //}

    }

    public void SolveLU(String outPath){
        //LUFactorization lu = new LUFactorization(A);
        Gauss lu = new Gauss(A);

        //Neyman a:
        //b[0]+=1;

        //Dirihlet a:
        b[0] = 0;
        b[1]-= 0*A.getValue(1, 0);
        A.setValue(0, 0, 1);
        A.setValue(0, 1, 0);
        A.setValue(1, 0, 0);

        //Dirihlet b:
        b[b.length-1] = 0;
        b[b.length-2]-= 0*A.getValue(b.length-2, b.length-1);
        A.setValue(A.getN()-1, A.getN()-1, 1);
        A.setValue(A.getN()-1, A.getN()-2, 0);
        A.setValue(A.getN()-2, A.getN()-1, 0);

//        for (int i = 0; i < b.length; i++) {
//            for (int j = 0; j < b.length; j++) {
//                System.out.print(A.getValue(i, j)+"\t");
//            }
//            System.out.println("\t"+b[i]);
//        }
        double[] res = lu.calculate(b);
        for (int j = 0; j < b.length; j++) {
            System.out.println(NodeList.get(j)+"\t"+res[j]);
        }
    }

    public static void main(String[] args){
        ArrayList<Double> list = new ArrayList<Double>();
        double a = 0;
        double b = 1;
        int N = 200;
        double h = (b-a)/N;
        for (int i = 0; i <= N; i++) {
            list.add(a+h*i);
        }
        //FEMShapeFunction1D1 f = new FEMShapeFunction1D1(0.5, 0.5);
        //for (int i = 0; i <= N; i++) {
        //    System.out.println((a+h*i)+"\t\t"+f.calculateDerivaty(a+h*i));
        //}
        MainMatrixGenerator1 gen = new MainMatrixGenerator1(list);
        gen.GenerateLU();
        gen.SolveLU("");
    }
}